{!{ define "go_generate_template" }!}
# <template: go_generate_template>
runs-on: [self-hosted, regular]
steps:
  {!{ tmpl.Exec "started_at_output"            . | strings.Indent 2 }!}
  {!{ tmpl.Exec "checkout_step"                . | strings.Indent 2 }!}
  {!{ tmpl.Exec "login_readonly_registry_step" . | strings.Indent 2 }!}
  {!{ tmpl.Exec "werf_install_step"            . | strings.Indent 2 }!}

  - name: Set up Go 1.21
    uses: actions/setup-go@v3
    with:
      go-version: '1.21'

  - name: Run go generate
    run: |
      {!{/* TODO replace with 'make generate' when make become available on runners */}!}
      (cd tools && go generate)
      (cd modules/500-upmeter/hooks/smokemini/internal/snapshot && go generate)

  - name: Check generated code
    run: |
      git diff --exit-code
# </template: go_generate_template>
{!{ end }!}

{!{ define "workflow_render_template" }!}
# <template: workflow_render_template>
runs-on: [self-hosted, regular]
steps:
  {!{ tmpl.Exec "started_at_output"            . | strings.Indent 2 }!}
  {!{ tmpl.Exec "checkout_step"                . | strings.Indent 2 }!}
  {!{ tmpl.Exec "login_readonly_registry_step" . | strings.Indent 2 }!}

  - name: Render GitHub workflow
    run: |
      cd .github
      ./render-workflows.sh

  - name: Check rendered files
    run: |
      git diff --exit-code
# </template: workflow_render_template>
{!{ end }!}

{!{ define "build_template" }!}
{!{- $ctx := index . 0 -}!}
{!{- $buildType := index . 1 -}!}
# <template: build_template>
runs-on: [self-hosted, regular]
outputs:
  tests_image_name: ${{ steps.build.outputs.tests_image_name }}
steps:
{!{ if eq $buildType "release" }!}
  {!{ tmpl.Exec "started_at_output" $ctx | strings.Indent 2 }!}
{!{ end }!}
  {!{ tmpl.Exec "checkout_full_step" $ctx | strings.Indent 2 }!}
  {!{ tmpl.Exec "login_dev_registry_step" $ctx | strings.Indent 2 }!}
  {!{ tmpl.Exec "login_readonly_registry_step" $ctx | strings.Indent 2 }!}
  {!{ tmpl.Exec "login_rw_registry_step" $ctx | strings.Indent 2 }!}
  {!{ tmpl.Exec "werf_install_step" $ctx | strings.Indent 2 }!}

  - name: Build and push deckhouse images
    id: build
    env:
      DECKHOUSE_REGISTRY_HOST: ${{secrets.DECKHOUSE_REGISTRY_HOST}}
      CI_COMMIT_TAG: ${{needs.git_info.outputs.ci_commit_tag}}
      CI_COMMIT_BRANCH: ${{needs.git_info.outputs.ci_commit_branch}}
      CI_COMMIT_REF_NAME: ${{needs.git_info.outputs.ci_commit_ref_name}}
{!{- if or (eq $buildType "release") (eq $buildType "pre-release") }!}
      CI_COMMIT_REF_SLUG: ${{needs.git_info.outputs.ci_commit_ref_slug}}
{!{- else }!}
      CI_COMMIT_REF_SLUG: ${{needs.pull_request_info.outputs.ref_slug}}
{!{- end }!}
    run: |
      # Extract REPO_SUFFIX from repository name: trim prefix 'deckhouse/deckhouse-'.
      REPO_SUFFIX=${GITHUB_REPOSITORY#deckhouse/deckhouse-}
      if [[ $REPO_SUFFIX == $GITHUB_REPOSITORY ]] ; then
        # REPO_SUFFIX should be empty for main repo 'deckhouse/deckhouse'.
        REPO_SUFFIX=
      fi

      # Put tags on produced images and push to dev and release repositories.
      #
      # There are 2 modes: "dev" and "release".
      # The "dev" mode builds branches only:
      # - Build using dev-registry as primary and deckhouse registry as secondary.
      # - Push dev and dev/install images with prNUM tags and push to dev-registry.
      # The "release" mode builds branches and tags:
      # - Build using dev-registry as primary and deckhouse registry as secondary.
      # - Push dev and dev/install images to dev-registry with tag equal to a branch name (main or release-X.Y).
      # - Build using deckhouse registry as primary and dev-registry as secondary.
      # - Push dev, dev/install and release-channel-version images to deckhouse registry with tag equels to a Git tag.

      # SRC_NAME is a name of image from werf.yaml.
      # SRC is a source image name (stage name from werf build report).
      # DST is an image name for docker push.
      function pull_push_rmi() {
        SRC_NAME=$1
        SRC=$2
        DST=$3
        echo "⚓️ 📥 [$(date -u)] Pull '${SRC_NAME}' image as ${SRC}."
        docker pull ${SRC}
        echo "⚓️ 🏷 [$(date -u)] Tag '${SRC_NAME}' image as ${DST}."
        docker image tag ${SRC} ${DST}
        echo "⚓️ 📤 [$(date -u)] Push '${SRC_NAME}' image as ${DST}."
        docker image push ${DST}
        echo "⚓️ 🧹 [$(date -u)] Remove local tag for '${SRC_NAME}'."
        docker image rmi ${DST} || true;
      }

      if [[ -n "${DEV_REGISTRY_PATH}" ]]; then export WERF_REPO="${DEV_REGISTRY_PATH}"; fi
      type werf && source $(werf ci-env github --verbose --as-file)

      # CE/EE/FE -> ce/ee/fe
      REGISTRY_SUFFIX=$(echo ${WERF_ENV} | tr '[:upper:]' '[:lower:]')

      # Registry path to publish images for Git branches.
      BRANCH_REGISTRY_PATH=
      # Registry path to publish images for Git tags.
      SEMVER_REGISTRY_PATH=

      if [[ -n ${DECKHOUSE_REGISTRY_HOST:-} ]] ; then
        # Build using dev-registry as primary repo and prod registry as secondary (ro) repo.
        # This build will put stages to "dev" registry. If "dev" registry is empty, existing stages are copied from prod registry.

        SECONDARY_REPO="--secondary-repo ${DECKHOUSE_REGISTRY_HOST}/deckhouse/${REGISTRY_SUFFIX}"

        if [[ -n "${CI_COMMIT_BRANCH}" && ! "${CI_COMMIT_BRANCH}" =~ ^(main|release-.+)$ ]]; then
          SECONDARY_REPO=
        fi

        werf build \
          ${SECONDARY_REPO} \
          --parallel=true --parallel-tasks-limit=5 \
          --report-path images_tags_werf.json
        BRANCH_REGISTRY_PATH="${DEV_REGISTRY_PATH}"
        SEMVER_REGISTRY_PATH="${DECKHOUSE_REGISTRY_HOST}/deckhouse"
      else
        # DECKHOUSE_REGISTRY_HOST is empty, so this repo is not the main repo.
        # Build using dev-registry as a single primary repo and push:
        # - branches to Dev registry to run e2e tests.
        # - semver tags to Github Container Registry for testing release process.
        werf build \
          --parallel=true --parallel-tasks-limit=5 \
          --report-path images_tags_werf.json
        BRANCH_REGISTRY_PATH="${DEV_REGISTRY_PATH}"
        SEMVER_REGISTRY_PATH="${GHA_TEST_REGISTRY_PATH}"
        echo "⚓️ 🧪 [$(date -u)] DECKHOUSE_REGISTRY_HOST is empty. Publish to Github Container Registry '${PROD_REGISTRY_PATH}'"
      fi

      # Publish images for Git branch.
      if [[ -n "${CI_COMMIT_BRANCH}" ]]; then
        # CI_COMMIT_REF_SLUG is a 'prNUM' for dev branches or 'main' for default branch.
        # Use it as image tag. Add suffix to not overlap with PRs in main repo.
        IMAGE_TAG=${CI_COMMIT_REF_SLUG}${REPO_SUFFIX:+-${REPO_SUFFIX}}

        echo "⚓️ 💫 [$(date -u)] Publish images to dev-registry for branch '${CI_COMMIT_BRANCH}' and edition '${WERF_ENV}' using tag '${IMAGE_TAG}' ..."

        echo "⚓️ 💫 [$(date -u)] Publish 'dev' image to dev-registry using tag ${IMAGE_TAG}".
        DECKHOUSE_IMAGE_SRC="$(jq -r '.Images."dev".DockerImageName' images_tags_werf.json)"
        DECKHOUSE_IMAGE=${BRANCH_REGISTRY_PATH}:${IMAGE_TAG}
        pull_push_rmi 'dev' ${DECKHOUSE_IMAGE_SRC} ${DECKHOUSE_IMAGE}

        echo "⚓️ 💫 [$(date -u)] Publish 'dev/install' image to dev-registry using tag ${IMAGE_TAG}".
        INSTALL_IMAGE_SRC="$(jq -r '.Images."dev/install".DockerImageName' images_tags_werf.json)"
        INSTALL_IMAGE=${BRANCH_REGISTRY_PATH}/install:${IMAGE_TAG}
        pull_push_rmi 'dev/install' ${INSTALL_IMAGE_SRC} ${INSTALL_IMAGE}

        echo "⚓️ 💫 [$(date -u)] Publish 'e2e-terraform' image to dev-registry using tag ${IMAGE_TAG}".
        INSTALL_IMAGE_SRC="$(jq -r '.Images."e2e-terraform".DockerImageName' images_tags_werf.json)"
        INSTALL_IMAGE=${BRANCH_REGISTRY_PATH}/e2e-terraform:${IMAGE_TAG}
        pull_push_rmi 'e2e-terraform' ${INSTALL_IMAGE_SRC} ${INSTALL_IMAGE}
      fi

{!{ if eq $buildType "release" }!}
      # Publish images for Git tag.
      if [[ -n "${CI_COMMIT_TAG}" ]]; then
        # The Git tag may contain a '+' sign, so use slugify for this situation.
        # Slugify doesn't change a tag with safe-only characters.
        IMAGE_TAG=$(werf slugify --format docker-tag "${CI_COMMIT_TAG}")

        echo "⚓️ 💫 [$(date -u)] Publish images for Git tag '${CI_COMMIT_TAG}' and registry suffix '${REGISTRY_SUFFIX}' using tag '${IMAGE_TAG}' ..."
        if [[ -n ${DECKHOUSE_REGISTRY_HOST} ]] ; then
          # Copy stages to prod registry from dev registry.
          werf build \
            --repo ${SEMVER_REGISTRY_PATH}/${REGISTRY_SUFFIX} \
            --secondary-repo $WERF_REPO \
            --parallel=true --parallel-tasks-limit=5 \
            --report-path images_tags_werf.json
        fi
        # Note: do not run second werf build for test repo, as it has no secondary repo.

        echo "⚓️ 💫 [$(date -u)] Publish 'dev' image to deckhouse registry using tag ${IMAGE_TAG} ..."
        DECKHOUSE_IMAGE_SRC="$(jq -r '.Images."dev".DockerImageName' images_tags_werf.json)"
        DECKHOUSE_IMAGE=${SEMVER_REGISTRY_PATH}/${REGISTRY_SUFFIX}:${IMAGE_TAG}
        pull_push_rmi 'dev' ${DECKHOUSE_IMAGE_SRC} ${DECKHOUSE_IMAGE}

        echo "⚓️ 💫 [$(date -u)] Publish 'dev/install' image to deckhouse registry using tag ${IMAGE_TAG} ..."
        INSTALL_IMAGE_SRC="$(jq -r '.Images."dev/install".DockerImageName' images_tags_werf.json)"
        INSTALL_IMAGE=${SEMVER_REGISTRY_PATH}/${REGISTRY_SUFFIX}/install:${IMAGE_TAG}
        pull_push_rmi 'dev/install' ${INSTALL_IMAGE_SRC} ${INSTALL_IMAGE}

        echo "⚓️ 💫 [$(date -u)] Publish 'release-channel-version' image to deckhouse registry using tag ${IMAGE_TAG} ..."
        RELEASE_CHANNEL_IMAGE_SRC="$(jq -r '.Images."release-channel-version".DockerImageName' images_tags_werf.json)"
        RELEASE_CHANNEL_IMAGE=${SEMVER_REGISTRY_PATH}/${REGISTRY_SUFFIX}/release-channel:${IMAGE_TAG}
        pull_push_rmi 'release-channel-version' ${RELEASE_CHANNEL_IMAGE_SRC} ${RELEASE_CHANNEL_IMAGE}
      fi
{!{- end }!}

      # Save 'tests' image name to pass it as output for 'tests' jobs.
      TESTS_IMAGE_NAME="$(jq -r '.Images."tests".DockerImageName' images_tags_werf.json)"
      # Print image name in uppercase to prevent hiding non-secret registry host stored in secret.
      echo "Tests image name: '${TESTS_IMAGE_NAME}'" | tr '[:lower:]' '[:upper:]'
      # Encode as gzip+base64 to evade github's SecretMasker error: "Skip output since it may contain secret".
      echo "tests_image_name=$(echo ${TESTS_IMAGE_NAME} | gzip | base64 -w0)" >> $GITHUB_OUTPUT

  - name: Cleanup
    if: ${{ always() }}
    run: |
      rm -f images_tags_werf.json
# </template: build_template>
{!{ end }!}
